/* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */
/* SPDX-License-Identifier: MIT */

/*
    31---------26-25-----21-20-----------------------------5--------0
    |  =COP2   | Special1 |                                |function|
    ------6----------5------------------------------------------6----
    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
000 |VADDx  |VADDy  |VADDz  |VADDw  |VSUBx  |VSUBy  |VSUBz  |VSUBw  |
001 |VMADDx |VMADDy |VMADDz |VMADDw |VMSUBx |VMSUBy |VMSUBz |VMSUBw |
010 |VMAXx  |VMAXy  |VMAXz  |VMAXw  |VMINIx |VMINIy |VMINIz |VMINIw |
011 |VMULx  |VMULy  |VMULz  |VMULw  |VMULq  |VMAXi  |VMULi  |VMINIi |
100 |VADDq  |VMADDq |VADDi  |VMADDi |VSUBq  |VMSUBq |VSUbi  |VMSUBi |
101 |VADD   |VMADD  |VMUL   |VMAX   |VSUB   |VMSUB  |VOPMSUB|VMINI  |
110 |VIADD  |VISUB  |VIADDI | ---   |VIAND  |VIOR   | ---   | ---   |
111 |VCALLMS|VCALLMSR| ---  | ---   |  *1   |  *1   |  *1   |  *1   |
 hi |-------|-------|-------|-------|-------|-------|-------|-------|
    *1=see special2 table
*/

    // TODO: properties

    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x00, vaddx,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x01, vaddy,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x02, vaddz,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x03, vaddw,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x04, vsubx,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // SUBtract broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x05, vsuby,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // SUBtract broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x06, vsubz,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // SUBtract broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x07, vsubw,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // SUBtract broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x08, vmaddx,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x09, vmaddy,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x0A, vmaddz,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x0B, vmaddw,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-ADD broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x0C, vmsubx,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-SUBtract broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x0D, vmsuby,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-SUBtract broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x0E, vmsubz,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-SUBtract broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x0F, vmsubw,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-SUBtract broadcast

    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x10, vmaxx,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MAXimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x11, vmaxy,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MAXimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x12, vmaxz,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MAXimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x13, vmaxw,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MAXimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x14, vminix,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MINimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x15, vminiy,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MINimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x16, vminiz,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MINimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x17, vminiw,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MINimum broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x18, vmulx,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MULtiply broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x19, vmuly,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MULtiply broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x1A, vmulz,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MULtiply broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x1B, vmulw,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MULtiply broadcast
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x1C, vmulq,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MULtiply Q
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x1D, vmaxi,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MAXimum I
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x1E, vmuli,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MULtiply I
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x1F, vminii,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MINImum I

    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x20, vaddq,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // ADD Q
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x21, vmaddq,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-ADD Q
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x22, vaddi,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // ADD I
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x23, vmaddi,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-ADD I
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x24, vsubq,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // SUBtract Q
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x25, vmsubq,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-SUBtract Q
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x26, vsubi,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // SUBtract I
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x27, vmsubi,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-SUBtract I
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x28, vadd,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // ADD
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x29, vmadd,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-ADD
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x2A, vmul,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MULtiply
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x2B, vmax,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MAXimum
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x2C, vsub,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // SUBtract
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x2D, vmsub,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Multiply-SUBtract
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x2E, vopmsub,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // Outer product post decrement
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x2F, vmini,
        .operands={RAB_OPERAND_r5900_vfdxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftxyzw},
        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
        .isFloat=true
    ) // MINImum

    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x30, viadd,
        .operands={RAB_OPERAND_r5900_vid, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_vit}
    ) // Integer ADD
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x31, visub,
        .operands={RAB_OPERAND_r5900_vid, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_vit}
    ) // Integer SUBtract
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x32, viaddi,
        .operands={RAB_OPERAND_r5900_vit, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_immediate5}
    ) // Integer ADD Immediate
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x34, viand,
        .operands={RAB_OPERAND_r5900_vid, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_vit}
    ) // Integer AND
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x35, vior,
        .operands={RAB_OPERAND_r5900_vid, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_vit}
    ) // Integer OR

    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x38, vcallms,
        .operands={RAB_OPERAND_r5900_immediate15}
    )
    RABBITIZER_DEF_INSTR_ID(
        r5900, 0x39, vcallmsr,
        .operands={RAB_OPERAND_r5900_vis}
    )
